package cn.iocoder.yudao.module.crm.controller.admin.performance.person;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.crm.controller.admin.performance.config.vo.PerformanceConfigDetailRespVO;
import cn.iocoder.yudao.module.crm.controller.admin.performance.person.vo.*;
import cn.iocoder.yudao.module.crm.controller.admin.statistics.vo.performance.CrmStatisticsPerformanceReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.performance.config.PerformanceConfigDetailDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.performance.person.PersonPerformanceConfigDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.performance.person.PersonPerformanceConfigDetailDO;
import cn.iocoder.yudao.module.crm.service.performance.person.PersonPerformanceConfigDetailService;
import cn.iocoder.yudao.module.crm.service.performance.person.PersonPerformanceConfigService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;

@Tag(name = "管理后台 - CRM_员工业绩配置")
@RestController
@RequestMapping("/crm/performance/person")
@Validated
public class PersonPerformanceConfigController {

    @Resource
    private PersonPerformanceConfigService personPerformanceConfigService;

    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private DeptApi deptApi;

    @Resource
    private PersonPerformanceConfigDetailService personPerformanceConfigDetailService;

    @PostMapping("/create")
    @Operation(summary = "创建CRM_业绩配置")
    @PreAuthorize("@ss.hasPermission('crm:performance:person:create')")
    public CommonResult<Boolean> createPerformanceConfig(@Valid @RequestBody PersonPerformanceConfigSaveReqVO createReqVO) {
        personPerformanceConfigService.createPerformanceConfig(createReqVO);
        return success(true);
    }

    @PutMapping("/update")
    @Operation(summary = "更新CRM_业绩配置")
    @PreAuthorize("@ss.hasPermission('crm:performance:person:update')")
    public CommonResult<Boolean> updatePerformanceConfig(@Valid @RequestBody PersonPerformanceConfigSaveReqVO updateReqVO) {
        personPerformanceConfigService.updatePerformanceConfig(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除CRM_业绩配置")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('crm:performance:person:delete')")
    public CommonResult<Boolean> deletePerformanceConfig(@RequestParam("id") Long id) {
        personPerformanceConfigService.deletePerformanceConfig(id);
        return success(true);
    }

    @DeleteMapping("/delete-list")
    @Parameter(name = "ids", description = "编号", required = true)
    @Operation(summary = "批量删除CRM_业绩配置")
                @PreAuthorize("@ss.hasPermission('crm:performance:person:delete')")
    public CommonResult<Boolean> deletePerformanceConfigList(@RequestParam("ids") List<Long> ids) {
        personPerformanceConfigService.deletePerformanceConfigListByIds(ids);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得CRM_业绩配置")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('crm:performance:person:query')")
    public CommonResult<PersonPerformanceConfigRespVO> getPerformanceConfig(@RequestParam("id") Long id) {
        PersonPerformanceConfigDO performanceConfig = personPerformanceConfigService.getPerformanceConfig(id);
        return success(BeanUtils.toBean(performanceConfig, PersonPerformanceConfigRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得CRM_业绩配置分页")
    @PreAuthorize("@ss.hasPermission('crm:performance:person:query')")
    public CommonResult<PageResult<PersonPerformanceConfigRespVO>> getPerformanceConfigPage(@Valid PersonPerformanceConfigPageReqVO pageReqVO) {
        PageResult<PersonPerformanceConfigDO> pageResult = personPerformanceConfigService.getPerformanceConfigPage(pageReqVO);
        return success(BeanUtils.toBean(pageResult, PersonPerformanceConfigRespVO.class));
    }

    @GetMapping("/resultList")
    @Operation(summary = "获得CRM_业绩配置")
    @PreAuthorize("@ss.hasPermission('crm:performance:person:query')")
    public CommonResult<List<PersonPerformanceConfigRespVO>> getPerformanceConfigResultList(@Valid PersonPerformanceConfigPageReqVO pageReqVO) {
        List<PersonPerformanceConfigDO> pageResult = personPerformanceConfigService.getPerformanceConfigResultList(pageReqVO);
        return success(BeanUtils.toBean(pageResult, PersonPerformanceConfigRespVO.class));
    }



    @GetMapping("/exportExcel")
    @Operation(summary = "导出CRM_业绩配置 Excel")
    @PreAuthorize("@ss.hasPermission('crm:performance:person:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportPerformanceConfigExcel(@Valid PersonPerformanceConfigPageReqVO pageReqVO,
              HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<PersonPerformanceConfigDO> list = personPerformanceConfigService.getPerformanceConfigPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "CRM_业绩配置.xls", "数据", PersonPerformanceConfigRespVO.class,
                        BeanUtils.toBean(list, PersonPerformanceConfigRespVO.class));
    }

    @GetMapping("/result/page")
    @Operation(summary = "获得CRM_业绩配置分页")
    @PreAuthorize("@ss.hasPermission('crm:performance:person:result:query')")
    public CommonResult<PageResult<PersonPerformanceConfigDetailRespVO>> getPerformanceConfigDetailPage(@Valid PersonPerformanceConfigDetailPageReqVO pageReqVO) {
        PageResult<PersonPerformanceConfigDetailDO> pageResult = personPerformanceConfigDetailService.getPerformanceConfigDetailPage(pageReqVO);
        pageResult.getList().stream().iterator().forEachRemaining(performanceConfigDetailDO -> {
            String pointType = performanceConfigDetailDO.getPerformancePoint();

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
            CrmStatisticsPerformanceReqVO performanceReqVO= null;
            try {
                performanceReqVO = parseQueryParam(performanceConfigDetailDO, sdf);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            String finishValue = getPerformance(performanceReqVO,pointType);
            performanceConfigDetailDO.setFinishValue(finishValue);
            performanceConfigDetailDO.updateFinishRate();
        });
        return success(BeanUtils.toBean(pageResult, PersonPerformanceConfigDetailRespVO.class));
    }

    private CrmStatisticsPerformanceReqVO parseQueryParam(PersonPerformanceConfigDetailDO performanceConfigDetailDO, SimpleDateFormat sdf) throws ParseException {
        CrmStatisticsPerformanceReqVO performanceReqVO = new CrmStatisticsPerformanceReqVO();
        performanceReqVO.setUserId(performanceConfigDetailDO.getUserId());
        String belongMonth = performanceConfigDetailDO.getBelongMonth();
        Date date = sdf.parse(belongMonth);
        Calendar calendarBegin = Calendar.getInstance();
        calendarBegin.setTime(date);
        calendarBegin.set(Calendar.DAY_OF_MONTH, 1);
        calendarBegin.set(Calendar.HOUR_OF_DAY, 0);
        LocalDateTime s = LocalDateTimeUtils.beginOfMonth(LocalDateTimeUtils.buildTime(calendarBegin.get(Calendar.YEAR), calendarBegin.get(Calendar.MONTH) + 1, calendarBegin.get(Calendar.DAY_OF_MONTH)));
        LocalDateTime e = LocalDateTimeUtils.endOfMonth(LocalDateTimeUtils.buildTime(calendarBegin.get(Calendar.YEAR), calendarBegin.get(Calendar.MONTH) + 1, calendarBegin.get(Calendar.DAY_OF_MONTH)));
        performanceReqVO.setTimes(new LocalDateTime[]{s,e}); // 数据起止范围
        return performanceReqVO;
    }

    /**
     * 获得员工业绩数据
     *
     * 1. 获得今年 + 去年的数据
     * 2. 遍历今年的月份，逐个拼接去年的月份数据
     *
     * @param performanceReqVO  参数
     * @param type 业绩指标点
     * @return 员工业绩数据
     */
    private String getPerformance(CrmStatisticsPerformanceReqVO performanceReqVO, String type) {

        // 1. 获得用户编号数组
        List<Long> userIds = getUserIds(performanceReqVO);
        if (CollUtil.isEmpty(userIds)) {
            return "0"; // 部门下没有员工 直接返回业绩为0
        }
        performanceReqVO.setUserIds(userIds);
        return personPerformanceConfigDetailService.getResult(performanceReqVO, type);
    }

    /**
     * 获取用户编号数组。如果用户编号为空, 则获得部门下的用户编号数组，包括子部门的所有用户编号
     *
     * @param reqVO 请求参数
     * @return 用户编号数组
     */
    private List<Long> getUserIds(CrmStatisticsPerformanceReqVO reqVO) {
        // 情况一：选中某个用户
        if (ObjUtil.isNotNull(reqVO.getUserId())) {
            return ListUtil.of(reqVO.getUserId());
        }
        // 情况二：选中某个部门
        // 2.1 获得部门列表
        final Long deptId = reqVO.getDeptId();
        List<Long> deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId);
        deptIds.add(deptId);
        // 2.2 获得用户编号
        return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId);
    }

}